import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

/**
 * Copyright 2013 李松泉 功能说明：TODO 开发时间：2013-12-27下午3:06:25 开发作者：李松泉
 */
public class AutoUpdate {
	
	private static String isLocal = "local";

	/**
	 * 文件传输方法
	 * @param photoUrl
	 * @param fileName
	 * @return
	 */
	private static boolean saveUrlAs(String photoUrl, String fileName) {
		try {
			File localFile = new File(fileName).getParentFile();
			if(!localFile.exists())
				localFile.mkdirs();
			URL url = new URL(photoUrl);
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestProperty("Content-Type", "*/*");
			DataInputStream in = new DataInputStream(connection.getInputStream());
			DataOutputStream out = new DataOutputStream(new FileOutputStream(fileName));
			byte[] buffer = new byte[4096];
			int count = 0;
			while ((count = in.read(buffer)) > 0) {
				out.write(buffer, 0, count);
			}
			out.close();
			in.close();
			return true;
		} catch (Exception e) {
			System.out.println(e);
			return false;
		}
	}

	/**
	 * 兼容HTTP和FTP协议
	 * 
	 * @param urlString
	 * @return
	 */
	public String getDocumentAt(String urlString) {
		StringBuffer document = new StringBuffer();
		try {
			URL url = new URL(urlString);
			URLConnection conn = url.openConnection();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				document.append(line + "\n");
			}
			reader.close();
		} catch (MalformedURLException e) {
			System.out.println("Unable to connect to URL: " + urlString);
		} catch (IOException e) {
			System.out.println("IOException when connecting to URL: " + urlString);
		}
		return document.toString();
	}

	/**
	 * 测试main方法
	 * @param args
	 */
	public static void main(String[] args) {
		File dir = new File("");
		String basepath = dir.getAbsolutePath(); 
		String updateUrl = "";
		try {
			File fClient = new File(basepath + "\\updateconfig.xml");//本地配置文件地址
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(fClient);
			updateUrl = doc.getElementsByTagName("Ip").item(0).getFirstChild().getNodeValue();//获取更新文件所在地址
			if(updateUrl.contains("http"))
				isLocal = "http";
			String updatePort = doc.getElementsByTagName("Port").item(0).getFirstChild().getNodeValue();
			System.out.println("update url = "+updateUrl);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		
		String photoUrl = updateUrl + "/updateconfig.xml";//服务器配置文件地址
		boolean flag = false;
		if(isLocal.equals("http"))//线上
			flag = saveUrlAs(photoUrl, basepath + "\\updateconfigServer.xml");
		else if(isLocal.equals("local"))//本地测试
			flag = saveLocalTest(photoUrl, basepath + "\\updateconfigServer.xml");
		if(!flag){
			System.out.println("更新失败！ ");
			return;
		}
			
		checkVersion(updateUrl,basepath + "\\updateconfigServer.xml");
		System.out.println("更新完成！已是最新版本 ");
	}

	/**
	 * 本地测试时传输文件
	 * @param photoUrl
	 * @param string
	 * @return
	 */
	private static boolean saveLocalTest(String photoUrl, String string) {
		try {
			File localFile = new File(string).getParentFile();
			if(!localFile.exists())
				localFile.mkdirs();
			FileInputStream in = new java.io.FileInputStream(photoUrl);
			FileOutputStream out = new FileOutputStream(string);
			byte[] bt = new byte[1024];
			int count;
			while ((count = in.read(bt)) > 0) {
				out.write(bt, 0, count);
			}
			in.close();
			out.close();
			return true;
		} catch (IOException ex) {
			return false;
		}
	}

	/**
	 * 比对客户端和服务端配置文件版本信息
	 * @param serverPath
	 * @param serverFilePath
	 */
	private static void checkVersion(String serverPath,String serverFilePath) {
		try {
			File f = new File(serverFilePath);
			File fClient = new File(f.getParentFile().getPath()+"\\updateconfig.xml");
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(f);
			Document docClient = builder.parse(fClient);
			String versionServer = doc.getElementsByTagName("Version").item(0).getFirstChild().getNodeValue();
			String versionClient = docClient.getElementsByTagName("Version").item(0).getFirstChild().getNodeValue();
			if(versionServer.equals(versionClient)){
				System.out.println("已是最新版本，不需要更新！");
				if(f != null)
					f.delete();
				return;
			}
			System.out.println("正在更新，请稍等...");	
			NodeList nl = doc.getElementsByTagName("File");
			for (int i = 0; i < nl.getLength(); i++) {//逐一比对配置文件中的文件版本是否一样
				String serverFileName = doc.getElementsByTagName("Name").item(i).getFirstChild().getNodeValue();
				String serverFilePath2 = doc.getElementsByTagName("Path").item(i).getFirstChild().getNodeValue();
				if(serverFilePath2.contains("./"))
					serverFilePath2 = serverFilePath2.substring(serverFilePath2.indexOf("./")+2)+"/";
				else if(serverFilePath2.contains(".\\"))
					serverFilePath2 = serverFilePath2.substring(serverFilePath2.indexOf(".\\")+2)+"/";
				if(docClient.getElementsByTagName("Name").item(i) == null){//如果客户端配置中不存在则把服务端的这个文件下载到客户端
					String fromFilePath = serverPath + "/"+serverFilePath2 + serverFileName;
					String toFilePath = fClient.getParentFile().getPath()+"\\"+serverFilePath2 + serverFileName;
					if(isLocal.equals("http"))//线上
						saveUrlAs(fromFilePath, toFilePath);
					else if(isLocal.equals("local"))
						saveLocalTest(fromFilePath, toFilePath);//本地测试
				}else{
					String clientFileName = docClient.getElementsByTagName("Name").item(i).getFirstChild().getNodeValue();
					String serverFileVersion = doc.getElementsByTagName("SubVer").item(i).getFirstChild().getNodeValue();
					String clientFileVersion = docClient.getElementsByTagName("SubVer").item(i).getFirstChild().getNodeValue();
					if (serverFileName.equals(clientFileName) && !serverFileVersion.equals(clientFileVersion)) {//如果客户端和服务端相同的文件版本不一样则把服务端的更新到客户端
						String fromFilePath = serverPath + "/"+serverFilePath2 + serverFileName;
						String toFilePath = fClient.getParentFile().getPath()+"\\"+serverFilePath2 + serverFileName;
						if(isLocal.equals("http"))//线上
							saveUrlAs(fromFilePath, toFilePath);
						else if(isLocal.equals("local"))
							saveLocalTest(fromFilePath, toFilePath);//本地测试
						if(serverFileName.lastIndexOf(".zip") > 0){
							ZipUtils.decompress(toFilePath);
						}
					}
				}
			}
			fClient.delete();
			File fNew = new File(f.getParentFile().getPath() + "\\updateconfig.xml");//更新服务端配置文件
			f.renameTo(fNew);
			
//			String url= "jdbc:oracle:thin:@172.17.12.65:1521:jxczp";
//			String username="opcard";
//			String password="opcard";
//			Connection conn = null;
//			Class.forName("oracle.jdbc.driver.OracleDriver");
//			conn = DriverManager.getConnection(url, username, password);
//			Statement stam = conn.createStatement();
//			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//			Date currentTime = new Date();
//			String currentTimeStr = formatter.format(currentTime);
//			String updateSql = "update opcard.T_C_UPDATEINFO set LASTUPDATETIME = '"+currentTimeStr+"', VERSION = '"+"1"+"' where APPNAME = 'czp'";
//			int updateResult = stam.executeUpdate(updateSql);
//			if(updateResult == 0){
//				int idNumber = new Random().nextInt(1000000000) + 1;
//				String insertSql = "insert into opcard.T_C_UPDATEINFO values ("+idNumber+",'"+"1"+"','"+currentTimeStr+"','"+currentTimeStr+"','czp')";
//				int insertResult = stam.executeUpdate(insertSql);
//				if(insertResult == 0)
//					System.out.println("插入更新记录失败！");
//			}
//			stam.close();
//			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
